/*
 * Intervalo.cpp
 *
 *  Created on: 03/06/2014
 *      Author: jubuntu
 */


#include "Intervalo.h"

Intervalo::Intervalo(){

	this->probabilidadDelCero = 0;
	this->techo = 0xffffffff;
	this->piso  = 0;
	this->contadorDeUnderflow = 0;
	this->cantidadDeBitsEnCharIncompleto = 0;
	this->charIncompleto = 0;
	this->bufferDeCharsAEscribir = new std::vector<Byte>();
}

void Intervalo::chequearSiSeCompletoElChar(){
	if (this->cantidadDeBitsEnCharIncompleto == 8){
		this->bufferDeCharsAEscribir->push_back(this->charIncompleto);
		this->cantidadDeBitsEnCharIncompleto = 0;
		std::cout << " 							EMITO: " << (unsigned int)(this->charIncompleto) << std::endl;
	}
}

Intervalo::~Intervalo(){
	delete this->bufferDeCharsAEscribir;
}

void Intervalo::expandirIntervaloCon(int numeroQueSalio){
	//Expando el intervalo dependiendo de qué bit fue leído
	//punto medio = piso + aux
	unsigned long int aux = ((double)(this->techo - this->piso)) * ((double)this->probabilidadDelCero);
	//std::cout << "AUX: " << aux << std::endl;
	if(numeroQueSalio == 0){
		this->techo = this->piso + aux;
	}else{
		this->piso = this->piso + aux;
	}
}

std::vector<Byte>* Intervalo::getString(){
	return this->bufferDeCharsAEscribir;
}

void Intervalo::normalizar(){

	 unsigned int mascaras[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
			2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152,
			4194304,8388608, 16777216, 33554432, 67108864, 134217728,
			268435456, 536870912, 1073741824, 2147483648};

	int MSBitTecho = 0;
	int MSBitPiso = 0;

	bool sonIguales = true;


	//VERIFICA OVERFLOW
	while (sonIguales){
			MSBitTecho = ( techo & mascaras[31]) >> 31 ;
			MSBitPiso = ( piso & mascaras[31]) >> 31;

		if (MSBitTecho == MSBitPiso) { //HAY OVERFLOW
			std::cout << "			Overflow con: " << MSBitTecho << std::endl;

			this->charIncompleto = this->charIncompleto << 1; //escribo el bit del overflow en el char incompleto
			this->charIncompleto = this->charIncompleto | MSBitTecho;
			this->cantidadDeBitsEnCharIncompleto++;
			this->chequearSiSeCompletoElChar(); //si el char incompleto tiene 8 bits, está completo. Lo guardo y reinicio.

			//AGREGO BITS DE UNDERFLOW
			for (;this->contadorDeUnderflow > 0; this->contadorDeUnderflow--){
				this->charIncompleto = this->charIncompleto << 1;
				if (MSBitTecho == 0){
					this->charIncompleto = this->charIncompleto | mascaras[0]; //LSB en 1
				}
				this->cantidadDeBitsEnCharIncompleto++; //NO ESTABA. CREERIA QUE VA!
				this->chequearSiSeCompletoElChar();
			}


			techo = techo << 1;
			techo = techo | mascaras[0]; //saco el MSBIt y agrego uno en LSBit
			piso = piso << 1; //idem pero le pongo un cero

		}else{
			sonIguales = false;
		}
	}

	//UNDERFLOW
	int bit31Techo,bitAnteriorTecho, bit31Piso, bitAnteriorPiso;
	bit31Techo = MSBitTecho;
	bit31Piso = MSBitPiso;
	int recorredor = 30;

	bitAnteriorTecho = (techo & mascaras[recorredor]) >> recorredor;
	bitAnteriorPiso = (piso & mascaras[recorredor]) >> recorredor;

	if ((bit31Techo == 1) && (bit31Piso == 0)){

		bool hayUnderflow = true;

		while ((hayUnderflow)&&(recorredor>=0)){
			if ((bitAnteriorTecho == 0) && (bitAnteriorPiso == 1)){
				this->contadorDeUnderflow ++;
				recorredor --;
				bitAnteriorTecho = (techo & mascaras[recorredor]) >> recorredor;
				bitAnteriorPiso = (piso & mascaras[recorredor]) >> recorredor;
			}else{
				hayUnderflow = false;
			}
		}

		if (contadorDeUnderflow > 0 ){

			techo = techo << contadorDeUnderflow ;
			techo = techo | mascaras[31]; //ASEGURO QUE 1º BIT EN 1
			//ahora agrego los unos por derecha para techo
			for (int i=0; i < contadorDeUnderflow; i++){
				techo = techo | mascaras[i];
			}

			piso = piso << contadorDeUnderflow;
			//piso = piso >> 1; //RESTAURO 1º BIT EN 0
			piso = piso & 0x7fffffff;
			//restauro el bit mas significativo,
			//creo que siempre es 0 pero por las dudas...
			//piso = piso + MSBitPiso*mascaras[31];
		}

	}

}
